package com.itheima.appserver.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.bean.copier.provider.BeanValueProvider;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.appserver.config.MyThreadLocal;
import com.itheima.commons.constants.Constants;
import com.itheima.commons.pojo.UserInfo;
import com.itheima.commons.pojo.Video;
import com.itheima.commons.utils.RelativeDateFormat;
import com.itheima.commons.vo.PageResult;
import com.itheima.commons.vo.QuanZiVo;
import com.itheima.dubbo.interfaces.CommentApi;
import com.itheima.dubbo.interfaces.PublishApi;
import com.itheima.dubbo.interfaces.UserInfoApi;
import org.bson.types.ObjectId;

import cn.hutool.core.util.ObjectUtil;
import com.itheima.appserver.excepiton.ErrInfo;
import com.itheima.appserver.excepiton.ErroResult;
import com.itheima.appserver.excepiton.MyEx;
import com.itheima.commons.pojo.Publish;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.sql.Struct;
import java.util.*;
import java.util.function.BiConsumer;

/**
 * @ClassName: PublishService
 * @Description:
 * @Author: Administrator
 * @Date: 2021/12/8 10:08
 */
@Service
public class PublishService {

    @Autowired
    IdService idService;

    @Autowired
    AlbumService albumService;

    @Autowired
    TimeLineService timeLineService;

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    @Reference
    CommentApi commentApi;

    @Reference
    PublishApi publishApi;

    @Reference
    UserInfoApi userInfoApi;

    //发布动态
    public void sendMovements(Map<String, Object> params, MultipartFile[] multipartFile) throws IOException {
        String textContent = (String) params.get("textContent");
        //判断文字内容
        if (ObjectUtil.hasEmpty(textContent)) {
            throw new MyEx(ErroResult.fail(ErrInfo.textError));
        }
        List<String> media = new ArrayList<>();
        //把图片上传至阿里oss
        if (ObjectUtil.isNotNull(multipartFile)) {
            for (MultipartFile file : multipartFile) {
                //String picUrl = UploadPicUtil.uploadPic(multipartFile.getBytes(), StrUtil.subAfter(multipartFile.getOriginalFilename(), ",", true));
                //media.add(picUrl);
                System.out.println("----------------------接受到了图片-----------------------");
                media.add("https://hztanhua.oss-cn-hangzhou.aliyuncs.com/images/2021/12/07/9b532552fb034033be46a12792dc6e9a.jpeg");
            }
        }

        Publish publish = new Publish();
        publish.setId(new ObjectId());
        publish.setPid(idService.createId("PUBLISH"));
        publish.setUserId(MyThreadLocal.getUserId());
        publish.setText(textContent);
        publish.setMedias(media);

        /*publish.setSeeType(0);
        publish.setSeeList(Lists.newArrayList());
        publish.setNotSeeList(Lists.newArrayList());
        publish.setLongitude("");
        publish.setLatitude("");
        publish.setLocationName("");
        publish.setCreated(0L);*/

        //返回朋友圈的id
        String publishId = publishApi.publish(publish);

        //把 朋友圈的id 保存到自己的相册中
        albumService.save(publishId);

        //把朋友圈id保存到好友列表的时间线中
        timeLineService.save(publishId);

    }

    //朋友圈动态
    public PageResult friendMovements(Integer page, Integer pagesize) {
        //直接去quanzi_time_line_id查询有哪些publishId
        //根据id查询有哪些朋友圈信息
        List<Publish> publish = publishApi.findPublish(MyThreadLocal.getUserId(), page, pagesize, Publish.class);
        //从朋友圈中获取对应用户id
        List<Long> userIds = CollUtil.getFieldValues(publish, "userId", Long.class);
        //根据对应用户id，查询用户信息
        Map<Long, UserInfo> userInfoMap = userInfoApi.findUserInfoByUserid(new UserInfo(), userIds);

        List<QuanZiVo> quanZiVoList = getQuanZiVos(publish, userInfoMap,Publish.class);
        System.out.println("数据是从mongoDB中获取的");
        return new PageResult(page, pagesize, 0L, quanZiVoList);

    }

    /**
     * 把两个类型的参数封装进QuanZiVo
     *
     * @param publishList
     * @param userInfoMap
     * @return
     */
    private List<QuanZiVo> getQuanZiVos(List<Publish> publishList, Map<Long, UserInfo> userInfoMap,Class t) {
        List<QuanZiVo> quanZiVoList = new ArrayList<>();
        for (Publish publish : publishList) {
            QuanZiVo quanZiVo = new QuanZiVo();
            // 圈子ID
            quanZiVo.setId(publish.getId().toHexString());
            // 圈子发布人ID
            quanZiVo.setUserId(publish.getUserId());
            // 圈子文本内容
            quanZiVo.setTextContent(publish.getText());
            // 圈子的图片
            quanZiVo.setImageContent(Convert.toStrArray(publish.getMedias()));
            // 圈子的发布时间
            quanZiVo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));

            // 获取发布人的信息
            UserInfo userInfo = userInfoMap.get(publish.getUserId());
            // 头像
            quanZiVo.setAvatar(userInfo.getLogo());
            // 昵称
            quanZiVo.setNickname(userInfo.getNickName());
            // 性别
            quanZiVo.setGender(userInfo.getSex() == 1 ? "man" : "woman");
            // 年龄
            quanZiVo.setAge(userInfo.getAge());
            // 标签
            quanZiVo.setTags(StrUtil.splitToArray(userInfo.getTags(), ","));


            // 评论相关
            // 点赞数
            Long likeCount = Convert.toLong(redisTemplate.opsForHash().get(Constants.MOVEMENTS_INTERACT_KEY + publish.getId(), Constants.MOVEMENT_LIKE_HASHKEY));
            // 说明当前这个圈子没有人点赞 或者有人点赞但是Redis中没值
            if (ObjectUtil.isNull(likeCount)) {
                // 从MongoDB中进行查询
                likeCount = commentApi.queryComment(publish.getId(), 1, t);
                // 把查询到数据给保存到Redis中
                redisTemplate.opsForHash().put(Constants.MOVEMENTS_INTERACT_KEY + publish.getId(), Constants.MOVEMENT_LIKE_HASHKEY, likeCount.toString());
            }
            quanZiVo.setLikeCount(Convert.toInt(likeCount));


            // 评论数
            Long commentCount = Convert.toLong(redisTemplate.opsForHash().get(Constants.MOVEMENTS_INTERACT_KEY + publish.getId(), Constants.MOVEMENT_COMMENT_HASHKEY));
            if (ObjectUtil.isNull(commentCount)) {
                // 从MongoDB中进行查询
                commentCount = commentApi.queryCommentCount(publish.getId());
                // 把查询到数据给保存到Redis中
                redisTemplate.opsForHash().put(Constants.MOVEMENTS_INTERACT_KEY + publish.getId(), Constants.MOVEMENT_COMMENT_HASHKEY, commentCount.toString());
            }
            quanZiVo.setCommentCount(Convert.toInt(commentCount));

            // 喜欢数
            Long loveCount = Convert.toLong(redisTemplate.opsForHash().get(Constants.MOVEMENTS_INTERACT_KEY + publish.getId(), Constants.MOVEMENT_LOVE_HASHKEY));
            if (ObjectUtil.isNull(loveCount)) {
                // 从MongoDB中进行查询

                loveCount = commentApi.queryComment(publish.getId(), 3, t);
                // 把查询到数据给保存到Redis中
                redisTemplate.opsForHash().put(Constants.MOVEMENTS_INTERACT_KEY + publish.getId(), Constants.MOVEMENT_LOVE_HASHKEY, loveCount.toString());
            }
            quanZiVo.setLoveCount(Convert.toInt(loveCount));

            // 是否点赞
            Boolean isLike = redisTemplate.opsForHash().hasKey(Constants.MOVEMENTS_INTERACT_KEY, Constants.MOVEMENT_ISLIKE_HASHKEY + MyThreadLocal.getUserId());
            if (!isLike) {
                // 从MongoDB中进行查询

                isLike = commentApi.queryCommentStatus( publish.getId(),1,MyThreadLocal.getUserId(),t);
                if (isLike) {
                    // 把查询到数据给保存到Redis中
                    redisTemplate.opsForHash().put(Constants.MOVEMENTS_INTERACT_KEY + publish.getId(), Constants.MOVEMENT_ISLIKE_HASHKEY + MyThreadLocal.getUserId(), "1");
                }
            }
            quanZiVo.setHasLiked(isLike ? 1 : 0);

            // 是否喜欢
            Boolean isLove = redisTemplate.opsForHash().hasKey(Constants.MOVEMENTS_INTERACT_KEY, Constants.MOVEMENT_ISLOVE_HASHKEY + MyThreadLocal.getUserId());
            if (!isLove) {
                // 从MongoDB中进行查询
                isLove = commentApi.queryCommentStatus(publish.getId(), 3, MyThreadLocal.getUserId(), t);
                if (isLove) {
                    // 把查询到数据给保存到Redis中
                    redisTemplate.opsForHash().put(Constants.MOVEMENTS_INTERACT_KEY + publish.getId(), Constants.MOVEMENT_ISLOVE_HASHKEY + MyThreadLocal.getUserId(), "1");
                }
            }
            quanZiVo.setHasLoved(isLove ? 1 : 0);
            // 写死距离
            quanZiVo.setDistance("1.2公里");

            quanZiVoList.add(quanZiVo);
        }
        return quanZiVoList;
    }

    /**
     * 查询推荐动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult recommendMovements(Integer page, Integer pagesize,Class t) {
        //先从redis中查询是否有
        //从redis表QUANZI_PUBLISH_RECOMMEND_ID查询pid
        String pids = redisTemplate.opsForValue().get(Constants.REDIS_PIDS + MyThreadLocal.getUserId());

        //如果推荐动态为空，则随机推荐
        List publishList;
        if (StrUtil.isBlank(pids)) {
            publishList = publishApi.random(pagesize, t);
        } else {
            List<String> pidsList = StrUtil.split(pids, ",");
            //根据pid查询publishId
            publishList = publishApi.findPublishByPidList(Convert.toList(Long.class, pidsList));
        }

        //查publishId，同时查userId
        List<Long> userIds = CollUtil.getFieldValues(publishList, "userId", Long.class);

        //通过userId查询UserInfo
        Map<Long, UserInfo> userInfoMap = userInfoApi.findUserInfoByUserid(new UserInfo(), userIds);



            //用publishList和userInfoMap封装进QuanZiVo
            List<QuanZiVo> quanZiVoList = getQuanZiVos(publishList, userInfoMap,t);
            return new PageResult(page, pagesize, 0L, quanZiVoList);

    }

    public QuanZiVo queryById(ObjectId publishid) {
        Publish publish = publishApi.findPublish(publishid);
        UserInfo userInfo = userInfoApi.findById(publish.getUserId());
        List<QuanZiVo> quanZiVos = getQuanZiVos(CollUtil.newArrayList(publish), MapUtil.of(userInfo.getUserId(), userInfo),Publish.class);
        return quanZiVos.get(0);

    }

    public PageResult queryAlbumList(Long userId, Integer page, Integer pageSize) {
        List<Publish> list = publishApi.findPublishByuserId(userId, page, pageSize);
        UserInfo userInfo = userInfoApi.findById(userId);

        List<QuanZiVo> quanZiVos = getQuanZiVos(list, MapUtil.builder(userId, userInfo).build(), Publish.class);
        return new PageResult(page, pageSize, 0L, quanZiVos);
    }
}
